# set up cmake to download the external projects
include(FetchContent)
cmake_policy(SET CMP0054 NEW)
cmake_minimum_required(VERSION 3.18)

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
	message("Building In Debug Mode")
	set(RELEASE false)
	set(DEBUG_FLAG "-g")
else()
	set(DEBUG_FLAG "-O3")
	set(RELEASE true)
endif()

project(web-ifc LANGUAGES CXX)
enable_testing()

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

# collect source files
file(GLOB WebIfcParsing parsing/*.cpp)
file(GLOB_RECURSE WebIfcGeometry geometry/*.cpp)
file(GLOB_RECURSE WebIfcGeometryH geometry/*.h)
file(GLOB WebIfcSchema schema/*.cpp)
file(GLOB WebIfcManager modelmanager/*.cpp)
file(GLOB WebIfcAPI web-ifc-wasm.cpp)
file(GLOB WebIfcUtility utility/*.cpp)
file(GLOB WebIfcTestSourceFiles test/*.cpp)
file(GLOB WebIfcTestingMain web-ifc-test.cpp)

# Print the contents of WebIfcGeometry
message("Contents of WebIfcGeometry:")

foreach(file ${WebIfcGeometry})
	message("${file}")
endforeach()

# Print the contents of WebIfcGeometryH
message("Contents of WebIfcGeometryH:")

foreach(file ${WebIfcGeometryH})
	message("${file}")
endforeach()

# download the external projects and save their paths
Message("Downloading FastFloat")
FetchContent_Declare(fastfloat GIT_REPOSITORY "https://github.com/fastfloat/fast_float" GIT_TAG "2b2395f9ac836ffca6404424bcc252bff7aa80e4" SOURCE_SUBDIR "../")
FetchContent_MakeAvailable(fastfloat)
FetchContent_GetProperties(fastfloat)

Message("Downloading TinyNURBS")

# FetchContent_Declare(tinynurbs GIT_REPOSITORY "https://github.com/pradeep-pyro/tinynurbs" GIT_TAG "2fc6562d71665312c6298f7c340bace1bcf1b7a1" SOURCE_SUBDIR "../")
FetchContent_Declare(tinynurbs GIT_REPOSITORY "https://github.com/QuimMoya/tinynurbs" GIT_TAG "47115cd9b6e922b27bbc4ab01fdeac2e9ea597a4" SOURCE_SUBDIR "../")
FetchContent_MakeAvailable(tinynurbs)
FetchContent_GetProperties(tinynurbs)

Message("Downloading TinyCPPTest")
FetchContent_Declare(tinycpptest GIT_REPOSITORY "https://github.com/kovacsv/TinyCppTest" GIT_TAG "12e42c8ac6e032ce450fb3f772ebdfd1ddc6008c" SOURCE_SUBDIR "../")
FetchContent_MakeAvailable(tinycpptest)
FetchContent_GetProperties(tinycpptest)

Message("Downloading GLM")
FetchContent_Declare(glm GIT_REPOSITORY "https://github.com/g-truc/glm" GIT_TAG "bf71a834948186f4097caa076cd2663c69a10e1e" SOURCE_SUBDIR "../")
FetchContent_MakeAvailable(glm)
FetchContent_GetProperties(glm)

Message("Downloading Earcut")
FetchContent_Declare(earcut GIT_REPOSITORY "https://github.com/mapbox/earcut.hpp" GIT_TAG "4811a2b69b91f6127a75e780de6e2113609ddabb" SOURCE_SUBDIR "../")
FetchContent_MakeAvailable(earcut)
FetchContent_GetProperties(earcut)

Message("Downloading CDT")
FetchContent_Declare(cdt GIT_REPOSITORY "https://github.com/artem-ogre/CDT" GIT_TAG "4d0c9026b8ec846fe544897e7111f8f9080d5f8a" SOURCE_SUBDIR "../")

# FetchContent_Declare(cdt GIT_REPOSITORY "https://github.com/artem-ogre/CDT" GIT_TAG "9d99b32ae56b26cd2781678dc4405c98b8679a9f" SOURCE_SUBDIR "../")
FetchContent_MakeAvailable(cdt)
FetchContent_GetProperties(cdt)

Message("Downloading spdlog")
FetchContent_Declare(spdlog GIT_REPOSITORY "https://github.com/gabime/spdlog" GIT_TAG "7e635fca68d014934b4af8a1cf874f63989352b7" SOURCE_SUBDIR "../")
FetchContent_MakeAvailable(spdlog)
FetchContent_GetProperties(spdlog)

Message("Downloading FUZZY")

# using a custom version of fuzzy-bools to silence some debug printf from the library that pollutes the output of the executables
# FetchContent_Declare(fuzzy GIT_REPOSITORY "https://github.com/CBenghi/fuzzy-bools" GIT_TAG "07faaad8cae623dd634b1c09b4b37b44bf645781" SOURCE_SUBDIR "../")
# FetchContent_Declare(fuzzy GIT_REPOSITORY "https://github.com/tomvandig/fuzzy-bools" GIT_TAG "a52c0f0c0667b7c875ae44e91e63a33c1813be64" SOURCE_SUBDIR "../")
# @pobr1 Improvement
FetchContent_Declare(fuzzy GIT_REPOSITORY "https://github.com/QuimMoya/fuzzy-bools" GIT_TAG "2cf2885065dcf5359dc42b9934cd7d0acb62f431" SOURCE_SUBDIR "../")
FetchContent_MakeAvailable(fuzzy)
FetchContent_GetProperties(fuzzy)
file(RENAME ${fuzzy_SOURCE_DIR}/src ${fuzzy_SOURCE_DIR}/fuzzy RESULT result) # specifying 'result' continues even if rename was already performed
file(GLOB FuzzyHeaders ${fuzzy_SOURCE_DIR}/fuzzy/*.h)
message(${WebIfcGeometryH})

Message("Downloads Finished")

function(PARAM_SETTER THE_EXECUTABLE)
	target_include_directories(${THE_EXECUTABLE} PUBLIC ${tinynurbs_SOURCE_DIR}/include)
	target_include_directories(${THE_EXECUTABLE} PUBLIC ${fastfloat_SOURCE_DIR}/include)
	target_include_directories(${THE_EXECUTABLE} PUBLIC ${cdt_SOURCE_DIR}/CDT/include)
	target_include_directories(${THE_EXECUTABLE} PUBLIC ${glm_SOURCE_DIR}/)
	target_include_directories(${THE_EXECUTABLE} PUBLIC ${glm_SOURCE_DIR}/glm)
	target_include_directories(${THE_EXECUTABLE} PUBLIC ${earcut_SOURCE_DIR}/include)
	target_include_directories(${THE_EXECUTABLE} PUBLIC ${fuzzy_SOURCE_DIR}/)
	target_include_directories(${THE_EXECUTABLE} PUBLIC ${spdlog_SOURCE_DIR}/include)

	if(NOT MSVC)
		target_compile_options(${THE_EXECUTABLE} PUBLIC "-Wall")
		target_compile_options(${THE_EXECUTABLE} PUBLIC "-Wextra")
		target_compile_options(${THE_EXECUTABLE} PUBLIC "-Wpedantic")
		target_compile_options(${THE_EXECUTABLE} PUBLIC "-pedantic")
		target_compile_options(${THE_EXECUTABLE} PUBLIC "-std=c++20")

		if(EMSCRIPTEN)
			target_compile_options(${THE_EXECUTABLE} PUBLIC "-fexperimental-library")
		endif()

		if(RELEASE)
			target_compile_options(${THE_EXECUTABLE} PUBLIC "-O3")
		endif()
	else()
		target_compile_options(${THE_EXECUTABLE} PUBLIC "-std:c++latest")
	endif()
endfunction()

if(EMSCRIPTEN)
	# build parameters for web-ifc
	add_executable(web-ifc ${WebIfcManager} ${WebIfcSchema} ${WebIfcParsing} ${WebIfcAPI} ${WebIfcUtility} ${WebIfcGeometry})
	param_setter(web-ifc)
	set_target_properties(web-ifc PROPERTIES LINK_FLAGS "${DEBUG_FLAG} --bind -flto --define-macro=REAL_T_IS_DOUBLE -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -sSTACK_SIZE=5MB -s EXPORT_NAME=WebIFCWasm -s MODULARIZE=1 -s ENVIRONMENT=web")

	add_executable(web-ifc-node ${WebIfcManager} ${WebIfcSchema} ${WebIfcParsing} ${WebIfcAPI} ${WebIfcUtility} ${WebIfcGeometry})
	param_setter(web-ifc-node)
	set_target_properties(web-ifc-node PROPERTIES LINK_FLAGS "${DEBUG_FLAG} --bind -flto --define-macro=REAL_T_IS_DOUBLE -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -sSTACK_SIZE=5MB -s EXPORT_NAME=WebIFCWasm -s MODULARIZE=1 ")

	# multi-treaded versions
	add_executable(web-ifc-mt ${WebIfcManager} ${WebIfcSchema} ${WebIfcParsing} ${WebIfcAPI} ${WebIfcUtility} ${WebIfcGeometry})
	param_setter(web-ifc-mt)
	target_compile_options(web-ifc-mt PUBLIC "-pthread")
	set_target_properties(web-ifc-mt PROPERTIES LINK_FLAGS "${DEBUG_FLAG} -pthread -s PTHREAD_POOL_SIZE=navigator.hardwareConcurrency --bind -flto --define-macro=REAL_T_IS_DOUBLE -sSTACK_SIZE=5MB -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s EXPORT_NAME=WebIFCWasm -s MODULARIZE=1 -s ENVIRONMENT=web,worker")
endif()

if(NOT EMSCRIPTEN)
	# build parameters for web-ifc-test
	add_executable(web-ifc-test ${WebIfcManager} ${WebIfcSchema} ${WebIfcParsing} ${WebIfcUtility} ${WebIfcGeometry} ${WebIfcTestSourceFiles})
	param_setter(web-ifc-test)
	target_include_directories(web-ifc-test PUBLIC ${tinycpptest_SOURCE_DIR}/Sources)

	add_test(web-ifc-test web-ifc-test)
	set_tests_properties(web-ifc-test PROPERTIES LABELS "web-ifc")

	# build parameters for web-ifc in testing environment
	add_executable(web-ifc ${WebIfcManager} ${WebIfcSchema} ${WebIfcParsing} ${WebIfcUtility} ${WebIfcGeometry} ${WebIfcTestingMain} "./test/io_helpers.cpp")
	param_setter(web-ifc)
	target_include_directories(web-ifc PUBLIC ${tinycpptest_SOURCE_DIR}/Sources)

	# comment these to prevent debug files being generated
	if(NOT RELEASE)
		target_compile_options(web-ifc PUBLIC "-DCSG_DEBUG_OUTPUT")
		target_compile_options(web-ifc PUBLIC "-DDEBUG_DUMP_SVG")
	endif()
endif()
